//
//  UtilConst.swift
//  VSDK
//
//  Created by Ink on 2024-03-12.
//

@_exported import Foundation
@_exported import UIKit
@_exported import RxSwift
@_exported import RxCocoa

public typealias ZMHandler = () -> ()
public typealias ZMCompletionHandler = ZMHandler
public typealias ZMDataHandler<T> = (_ value: T?) -> ()
public typealias ZMValueHandler = ZMDataHandler<Any>

let ZM_BUNDLEID = Bundle.main.bundleIdentifier ?? "ZM.bundleIdentifier"

public var zmIsDebug: Bool { DeviceUtils.isDebugEnvironment}

@discardableResult
public func Debug<T>(_ block: () throws -> T) rethrows -> T? {
    #if DEBUG
    return try block()
    #else
    return nil
    #endif
}

// MARK: - method

import os
@available(iOS 14.0, *)
private let logger = Logger(subsystem: ZM_BUNDLEID, category: "debug")

/// 控制台打印
func print<T>(_ message: T,
              file: String = #file,
              method: String = #function,
              line: Int = #line) {
#if DEBUG
    let dateformatter = DateFormatter()
    dateformatter.dateFormat = "yyyy-MM-dd HH:mm:ss.SSS"
    let time = dateformatter.string(from: Date())
    
    let fileName = (file as NSString).lastPathComponent
    let header = "\(time) \(fileName)[\(line)], \(method)"
    
    if #available(iOS 14.0, *) {
        logger.debug("\(header) \(String(describing: message))")
    } else {
        Swift.print("\(header) \(String(describing: message))")
    }
#endif
}

public extension DispatchQueue {
    func saync(_ delay: TimeInterval = 0, _ execute: DispatchWorkItem) {
        if delay == 0 {
            async(execute:execute)
        }
        else {
            asyncAfter(deadline: .now() + delay, execute: execute)
        }
    }
}

public func ZAsync(queue:DispatchQueue = .global(), _ delay: TimeInterval = 0, _ execute: DispatchWorkItem) {
    queue.saync(delay, execute)
}

public func ZAsync(queue:DispatchQueue = .global(), _ delay: TimeInterval = 0, _ work: @escaping @convention(block) () -> Void) {
    ZAsync(delay, DispatchWorkItem(block: work))
}

public func MainAsync(_ delay: TimeInterval = 0, _ execute: DispatchWorkItem) {
    ZAsync(queue: DispatchQueue.main, delay, execute)
    if delay == 0 {
        DispatchQueue.main.async(execute: execute)
    }
    else {
        ZAsync(queue: DispatchQueue.main, delay, execute)
    }
}

public func MainAsync(_ delay: TimeInterval = 0, _ work: @escaping @convention(block) () -> Void) {
    if delay == 0 {
        DispatchQueue.main.async(execute: work)
    }
    else {
        MainAsync(delay, DispatchWorkItem(block: work))
    }
}

open class TaskQueue {
    
    private var maxTaskCount = 1
    private var isExecuting = false
    private var pendingTasks: [(@escaping () -> Void) -> Void] = [] // 存储多个排队的任务
    
    public init(maxCount: Int = 1) {}
    
    public func enqueueTask(isAsync: Bool = false, firstDelay: Bool = false, delay: TimeInterval = 0,  task: @escaping (@escaping () -> Void) -> Void) {
        if !isExecuting {
            // 没有任务执行时，立即执行
            isExecuting = true
            if firstDelay {
                append(task: task)
                self.taskDidComplete(isAsync:isAsync,delay: delay)
            }
            else {
                executeTask(task,isAsync:isAsync, delay: delay)
            }
        } else {
            append(task: task)
        }
    }
    
    private func append(task: @escaping (@escaping () -> Void) -> Void) {
        // 添加到队列
        pendingTasks.append(task)
        if pendingTasks.count > self.maxTaskCount {
            pendingTasks.removeFirst()
        }
    }
    
    private func executeTask(_ task: @escaping (@escaping () -> Void) -> Void, isAsync: Bool = false, delay: TimeInterval) {
        if isAsync {
            task { [weak self] in
                guard let self = self else { return }
                self.taskDidComplete(isAsync:isAsync,delay: delay)
            }
        }
        else {
            task(){}
            self.taskDidComplete(isAsync:isAsync,delay: delay)
        }
        
    }
    
    private func taskDidComplete(isAsync: Bool = false,delay: TimeInterval) {
        MainAsync(delay) { [weak self] in
            guard let self = self else { return }
            if let nextTask = self.pendingTasks.first {
                // 取出下一个任务并执行
                self.pendingTasks.removeFirst()
                self.executeTask(nextTask,isAsync:isAsync, delay: delay)
            } else {
                // 队列为空，重置状态
                self.isExecuting = false
            }
        }
    }
}

extension DispatchGroup {
    /// 执行多个异步任务并在所有任务完成后回调
    public static func performTasks(
        tasks: [(@escaping () -> Void) -> Void],
        completion: @escaping () -> Void
    ) {
        let dispatchGroup = DispatchGroup()
        
        for task in tasks {
            dispatchGroup.enter()
            task {
                // 每个任务完成时调用 leave
                dispatchGroup.leave()
            }
        }
        
        dispatchGroup.notify(queue: .main) {
            // 所有任务完成后回调
            completion()
        }
    }
    
    public static func performSyncTasks(
        tasks: [() -> Void],
        completion: @escaping () -> Void
    ) {
        let dispatchGroup = DispatchGroup()
        
        for task in tasks {
            dispatchGroup.enter()
            DispatchQueue.global().async {
                task()
                dispatchGroup.leave()
            }
        }
        
        dispatchGroup.notify(queue: .main) {
            completion()
        }
    }
}
